package com.levelup.cr.dao.fs;

import com.levelup.cr.model.bridge.NodeProxyResolver;
import com.levelup.cr.model.Node;
import com.levelup.cr.model.NodeProxy;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * User: Denis_Zavadsky
 * Date: 8/17/13
 * Time: 12:40 PM
 * To change this template use File | Settings | File Templates.
 */
@Component("fsNodeReader")
public class FSNodeReader extends FSAccessorAware {
    public static final int CURRENT_NESTED_LEVEL = 0;
    public static final int INFINITY_NESTED_LEVEL = -1;

    public Node readNode(String nodePath){
        return  readNode(nodePath,0);

    }

    public Node readNode(String nodePath, int nestedLevel){
        String[] nodeNames = nodePath.split(File.separator);
        int lastNode = nodeNames.length - 1;
        String nodeName = nodeNames[lastNode];
        String parentName = nodeNames[lastNode-1];
        String rootPath = nodePath.substring(0,nodePath.indexOf(nodeName));

        return readNodeFromFS(rootPath, nodeName, parentName, nestedLevel);
    }

    private Node readNodeFromFS(String rootPath, String nodeName, String parentName, int nestedLevel){
        FSNodeAccessor fsNodeAccessor =  createFSNodeAccessor(rootPath, nodeName);
        Node node = new Node();
        List<String> nodeChilds = null;
        try {
            node.setProperties(readPropertiesFromFS(fsNodeAccessor.getPropertiesFile()));
        } catch (IOException e) {

        }
        try {
            nodeChilds = readChildsFromFS(fsNodeAccessor.getNodelistFile());
        } catch (IOException e) {

        }
        node.setName(fsNodeAccessor.getNodeName());

        if (nestedLevel==CURRENT_NESTED_LEVEL){
            if (parentName==null || parentName.isEmpty()){
                node.setRoot(true);
            } else {
                String parentPath = fsNodeAccessor.getPath();
                Node parentProxy = createParentProxy(parentName,parentPath);
                node.setParent(parentProxy);
                node.setRoot(false);
            }

            if (!nodeChilds.isEmpty()){
                List<Node> childs = new ArrayList<Node>();
                for (String child : nodeChilds){
                    NodeProxy childProxy = new NodeProxy();
                    String[] parts = child.split("=");
                    childProxy.setName(parts[0]);
                    String parentPath = fsNodeAccessor.getPath()+File.separator+nodeName;
                    childProxy.setParentPath(parentPath);
                    NodeProxyResolver resolver = (NodeProxyResolver)applicationContext.getBean("nodeProxyResolver");
                    childProxy.setResolver(resolver);
                    childProxy.setRoot(false);
                    childs.add(childProxy);
                }
                node.setChilds(childs);
            }
        }
        if (nestedLevel==INFINITY_NESTED_LEVEL){
            if (parentName==null || parentName.isEmpty()){
                node.setRoot(true);
            } else {
                String parentPath = fsNodeAccessor.getPath();
                Node parentProxy = createParentProxy(parentName,parentPath);
                node.setParent(parentProxy);
                node.setRoot(false);
            }
            String currentRootPath = rootPath+File.separator+nodeName;
            List<Node> childs = new ArrayList<Node>();
            for (String child : nodeChilds){
                String[] parts = child.split("=");
                Node childNode = readNodeFromFS(currentRootPath, parts[0], nodeName, nestedLevel);
                childNode.setParent(node);
                childs.add(childNode);
            }
            node.setChilds(childs);

        }

        if (nestedLevel > CURRENT_NESTED_LEVEL){
            if (parentName==null || parentName.isEmpty()){
                node.setRoot(true);
            } else {
                String parentPath = fsNodeAccessor.getPath();
                Node parentProxy = createParentProxy(parentName,parentPath);
                node.setParent(parentProxy);
                node.setRoot(false);
            }
            String currentRootPath = rootPath+File.separator+nodeName;
            List<Node> childs = new ArrayList<Node>();
            for (String child : nodeChilds){
                String[] parts = child.split("=");
                Node childNode = readNodeFromFS(currentRootPath, parts[0], nodeName, nestedLevel-1);
                childNode.setParent(node);
                childs.add(childNode);
            }
            node.setChilds(childs);
        }

        return node;
    }

    private Node createParentProxy(String parentName, String parentPath){
        NodeProxy parentProxy = new NodeProxy();
        parentProxy.setName(parentName);

        parentPath = parentPath.replace(File.separator+parentName,"");
        parentProxy.setParentPath(parentPath);
        NodeProxyResolver resolver = (NodeProxyResolver)applicationContext.getBean("nodeProxyResolver");
        parentProxy.setResolver(resolver);
        return parentProxy;
    }

    private HashMap<String, Object> readPropertiesFromFS(File propertiesFile) throws IOException {
        HashMap<String, Object> properies = new HashMap<String, Object>();
        BufferedReader reader = new BufferedReader(new FileReader(propertiesFile));
        String line;
        while ( (line = reader.readLine())!=null) {
            String[] lines = line.split("=");
            if (lines.length==2){
                properies.put(lines[0],lines[1]);
            }

        }
        reader.close();
        return  properies;
    }

    private List<String> readChildsFromFS(File childsFile) throws IOException {
        List<String> childs = new ArrayList<String>();
        BufferedReader reader = new BufferedReader(new FileReader(childsFile));
        String line;
        while ( (line = reader.readLine())!=null) {
            childs.add(line);
        }
        reader.close();
        return childs;
    }

}
